package org.fglxy.mockserver.netty;

import java.util.concurrent.TimeUnit;

import org.fglxy.mockserver.mock.IMockEnd;
import org.fglxy.mockserver.netty.dynamic.DynamicProtoDecode;
import org.fglxy.mockserver.netty.dynamic.DynamicProtoEncode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class NettyServer {
	private static Logger LOGGER = LoggerFactory.getLogger(NettyServer.class);
	// 服务器端口
	private int serverPort;

	private EventLoopGroup bossGroup;

	private EventLoopGroup workerGroup;

	private ServerBootstrap boot;
	// 处理链
	private ChannelInitializer<SocketChannel> handler;

	private Channel channel;

	public NettyServer(int serverPort) {
		this.serverPort = serverPort;
	}
	
	public void release() {
		if (this.bossGroup != null && !this.bossGroup.isShutdown()) {
			this.bossGroup.shutdownGracefully(0, 2, TimeUnit.SECONDS);
		}
		if (this.workerGroup != null && !this.workerGroup.isShutdown()) {
			this.workerGroup.shutdownGracefully(0, 2, TimeUnit.SECONDS);
		}
	}

	public void start(IMockEnd server) throws InterruptedException {
		this.bossGroup = new NioEventLoopGroup(); // bossGroup就是parentGroup，是负责处理TCP/IP连接的
		this.workerGroup = new NioEventLoopGroup(); // workerGroup就是childGroup,是负责处理Channel(通道)的I/O事件

		this.boot = new ServerBootstrap();
		this.boot.group(this.bossGroup, this.workerGroup).channel(NioServerSocketChannel.class)
				.localAddress(serverPort); // 使用NioSocketChannel来作为连接用的Channel类
		
		if (this.handler == null) {
			this.handler = new ChannelInitializer<SocketChannel>() {
				
				@Override
				protected void initChannel(SocketChannel ch) throws Exception {
					ch.pipeline().addLast(new DynamicProtoDecode(server)).addLast(new DynamicProtoEncode());
				}

			};
		}
		this.boot.childHandler(handler);
		// 发起连接请求
		final ChannelFuture future = this.boot.bind().sync();
		
		this.channel = future.channel();
		LOGGER.info("server start in {}", this.serverPort);
	}
	
	public Channel getChannel() {
		return this.channel;
	}
}
